import axios from "axios";
import type {
  AxiosError,
  AxiosInstance,
  AxiosRequestConfig,
  AxiosResponse,
  InternalAxiosRequestConfig
} from "axios";
import { AxiosLoading } from "./loading";
import type { RequestConfigExtra } from "./request";
import { ContentTypeEnum, RequestEnum } from "@/enums/http-enum";
import router from "@/router";
// import { message, notification } from "ant-design-vue";

export interface ResponseBody<T = any> {
  Code: number;
  Message: string;
  Count: number;
  Meta: any;
  Data?: T;
}

const instance: AxiosInstance = axios.create({
  baseURL: import.meta.env.VITE_APP_API ?? "/",
  timeout: 60000,
  headers: { "Content-Type": ContentTypeEnum.JSON }
});
const axiosLoading = new AxiosLoading();
async function requestHandler(
  config: InternalAxiosRequestConfig & RequestConfigExtra
): Promise<InternalAxiosRequestConfig> {
  // 处理请求前的url
  if (
    import.meta.env.DEV &&
    import.meta.env.VITE_APP_BASE_API_DEV &&
    import.meta.env.VITE_APP_BASE_URL_DEV &&
    config.customDev
  ) {
    //  替换url的请求前缀baseUrl
    config.baseURL = import.meta.env.VITE_APP_BASE_API_DEV;
  }
  const token = useAuthorization();

  if (token.value && config.token !== false)
    config.headers.set(STORAGE_AUTHORIZE_KEY, token.value);

  // 增加多语言的配置
  // const { locale } = useI18nLocale();
  // config.headers.set("Accept-Language", locale.value ?? "zh-CN");
  if (config.loading) axiosLoading.addLoading();
  return config;
}

function responseHandler(
  response: any
): ResponseBody<any> | AxiosResponse<any> | Promise<any> | any {
  let refresh_token =
    response.headers[STORAGE_AUTHORIZE_KEY.toLocaleLowerCase()];
  if (refresh_token) {
    useAuthorization().value = refresh_token;
    console.log("refresh_token", refresh_token);
  }
  return response.data;
}

function errorHandler(error: AxiosError): Promise<any> {
  const token = useAuthorization();
  const notification = useNotification();

  if (error.response) {
    const { data, status, statusText } =
      error.response as AxiosResponse<ResponseBody>;
    if (status === 401) {
      notification?.error({
        message: "401",
        description: data?.Message || statusText,
        duration: 3
      });
      /**
       * 这里处理清空用户信息和token的逻辑，后续扩展
       */
      token.value = null;
      router
        .push({
          path: "/login",
          query: {
            redirect: router.currentRoute.value.fullPath
          }
        })
        .then(() => {});
    } else if (status === 403) {
      notification?.error({
        message: "403",
        description: data?.Message || statusText,
        duration: 3
      });
    } else if (status === 500) {
      notification?.error({
        message: "500",
        description: data?.Message || statusText,
        duration: 3
      });
    } else {
      notification?.error({
        message: "服务错误",
        description: data?.Message || statusText,
        duration: 3
      });
    }
  }
  return Promise.reject(error);
}

interface AxiosOptions<T> {
  url: string;
  params?: T;
  data?: T;
}
instance.interceptors.request.use(requestHandler);

instance.interceptors.response.use(responseHandler, errorHandler);

/** 后台服务器业务逻辑错误处理钩子 */
function handleServerException(
  res: ResponseBody<any>,
  options: AxiosOptions<any> & RequestConfigExtra
) {
  switch (res.Code) {
    case 500:
      // notification.error({
      //   message: `API ${res.Code}:${res.Message}`,
      //   description: options.url
      // });
      break;
    default:
      break;
  }
}

export default instance;
function instancePromise<R = any, T = any>(
  options: AxiosOptions<T> & RequestConfigExtra,
  handle: boolean = true
): Promise<ResponseBody<R>> {
  const { loading } = options;
  return new Promise((resolve, reject) => {
    instance
      .request(options)
      .then((res: any) => {
        if (handle) {
          handleServerException(res, options);
        }
        resolve(res as any);
      })
      .catch((e: Error | AxiosError) => {
        reject(e);
      })
      .finally(() => {
        if (loading) axiosLoading.closeLoading();
      });
  });
}
/**
 *  Get请求
 * @param url api地址
 * @param params 提交参数
 * @param config 请求额外配置信息
 * @param handle 是否使用钩子处理后台业务逻辑错误,默认处理
 * @returns Promise
 */
export function requestGet<R = any, T = any>(
  url: string,
  params?: T,
  config?: AxiosRequestConfig & RequestConfigExtra,
  handle: boolean = true
): Promise<ResponseBody<R>> {
  const options = {
    url,
    params,
    method: RequestEnum.GET,
    ...config
  };
  return instancePromise<R, T>(options, handle);
}

/**
 *  Post请求
 * @param url api地址
 * @param params 提交参数
 * @param config 请求额外配置信息
 * @param handle 是否使用钩子处理后台业务逻辑错误,默认处理
 * @returns Promise
 */
export function requestPost<R = any, T = any>(
  url: string,
  data?: T,
  config?: AxiosRequestConfig & RequestConfigExtra,
  handle: boolean = true
): Promise<ResponseBody<R>> {
  const options = {
    url,
    data,
    method: RequestEnum.POST,
    ...config
  };
  return instancePromise<R, T>(options, handle);
}

export function requestPostForm<R = any, T = any>(
  url: string,
  data?: T,
  config?: AxiosRequestConfig & RequestConfigExtra
): Promise<ResponseBody<R>> {
  const options = {
    url,
    data,
    method: RequestEnum.POST,
    headers: {
      "Content-Type": ContentTypeEnum.FORM_URLENCODED
    },
    ...config
  };
  return instancePromise<R, T>(options);
}

export function requestPut<R = any, T = any>(
  url: string,
  data?: T,
  config?: AxiosRequestConfig & RequestConfigExtra
): Promise<ResponseBody<R>> {
  const options = {
    url,
    data,
    method: RequestEnum.PUT,
    ...config
  };
  return instancePromise<R, T>(options);
}

export function requestDelete<R = any, T = any>(
  url: string,
  data?: T,
  config?: AxiosRequestConfig & RequestConfigExtra
): Promise<ResponseBody<R>> {
  const options = {
    url,
    data,
    method: RequestEnum.DELETE,
    ...config
  };
  return instancePromise<R, T>(options);
}
